home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * DUMPAOUT - Dump data about a GNU a.out-format object module.
- *
- * This is a simple utility without a lot of bells and whistles.
- * Throw a bogus or broken a.out file at it and it'll probably
- * crash. I wrote it mainly to help me determine that I had the
- * HSC JAS assembler properly emitting regulation a.out modules.
- *
- * GEMDOS file I/O and memory allocation is used, not because I
- * have anything against runtime libraries so much as that it
- * provides independence from size_t/int/long portability issues.
- *
- * This file is self-contained; there are no other source modules
- * or header files other than standard compiler headers. It was
- * written for HSC, and doesn't contain prototypes.
- *
- * Don't let the appearance of the term 'GNU' fool you: this is
- * public domain software, free of any encumbrances whatsoever.
- * There are no facist restrictions on copying or using this code
- * in any way you see fit.
- *
- * 06/16/93 v1.0 (Ian Lepore)
- * Created.
- *****************************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <osbind.h>
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
-
- #ifdef __BORLANDC__ /* %@#!^@%#$@# Borland compiler won't define */
- #define __STDC__ /* __STDC__ unless you ask for Pure-ANSI mode. */
- #endif /* (And nothing works right in its Pure-ANSI.) */
-
- /*----------------------------------------------------------------------------
- * structures and constants used with a.out modules.
- * cobbled together from the manpage for a.out on a Sun system,
- * mainly by deleting massive amounts of unneeded (by me) stuff.
- *--------------------------------------------------------------------------*/
-
- typedef struct { /* a.out module file header... */
- unsigned long a_info; /* typical magic value identifies file */
- unsigned long a_text; /* length of text, in bytes */
- unsigned long a_data; /* length of data, in bytes */
- unsigned long a_bss; /* length of uninitialized data area in bytes */
- unsigned long a_syms; /* length of symbol table data in bytes */
- unsigned long a_entry; /* start address (unused in object modules) */
- unsigned long a_trsize; /* length of relocation info for text, in bytes */
- unsigned long a_drsize; /* length of relocation info for data, in bytes */
- } EXEC;
-
- #define A_OUT_MAGIC 0407 /* value of exec.a_info for object module */
-
- typedef struct { /* symbol for a.out file... */
- long n_strx;
- unsigned char n_type;
- char n_other;
- short n_desc;
- unsigned long n_value;
- } NLIST;
-
- #define N_UNDF 0 /* symbol n_type flag values... */
- #define N_EXT 1
- #define N_ABS 2
- #define N_TEXT 4
- #define N_DATA 6
- #define N_BSS 8
- #define N_FN 15
- #define N_COMM 18
-
- typedef struct { /* reloc directive for a.out file... */
- unsigned long r_address;
- unsigned long r_symboldat;
- } RINFO;
-
- #define RINFO_PCREL 0x80 /* values ORed into low byte of */
- #define RINFO_LONG 0x40 /* rinfo.r_symboldat */
- #define RINFO_WORD 0x20
- #define RINFO_EXT 0x10
-
- /*----------------------------------------------------------------------------
- * internal data.
- *--------------------------------------------------------------------------*/
-
- static EXEC thehdr;
- static short inhandle;
- static char *fname;
- static char *strtab;
- static NLIST *symtab;
-
- static char *text;
- static char *data;
-
- static long nsyms;
- static long ntrelocs;
- static long ndrelocs;
-
- static long toffset;
- static long doffset;
- static long treloffset;
- static long dreloffset;
- static long symoffset;
- static long stroffset;
-
- /*----------------------------------------------------------------------------
- * code.
- *--------------------------------------------------------------------------*/
-
- #ifdef __STDC__
- void fatal(char *,...);
- void gfree(void *);
- void *emalloc(long);
- void read_error(char *);
- void load_show_header(void);
- void load_text(void);
- void load_data(void);
- void load_symbol_data(void);
- void show_a_symbol(NLIST *);
- void load_show_symbol_table(void);
- void show_a_reloc(RINFO *,char *);
- void load_show_reloc(char *,char *,long,long);
- void load_show_file(char *);
- int main(int,char **);
- #endif
-
- /*----------------------------------------------------------------------------
- * service routines.
- *--------------------------------------------------------------------------*/
-
- #ifdef __STDC__
- static void fatal(char *fmt, ...)
- #else
- static void fatal(fmt)
- char *fmt;
- #endif
- /*****************************************************************************
- * whine and die.
- ****************************************************************************/
- {
- va_list args;
-
- fputs("dumpaout (fatal): ", stderr);
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fputc('\n', stderr);
- exit(1);
- }
-
- static void gfree(block)
- void *block;
- /*****************************************************************************
- * gentle-free; free the block if the pointer is non-NULL.
- ****************************************************************************/
- {
- if (block) {
- Mfree(block);
- }
- }
-
- static void *emalloc(size)
- long size;
- /*****************************************************************************
- * allocate a block; whine and die if it fails.
- ****************************************************************************/
- {
- void *block;
-
- if (NULL == (block = (void*)Malloc(size))) {
- fatal("out of memory processing file %s, asked for %ld", fname, size);
- }
- return block;
- }
-
- static void read_error(type)
- char *type;
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- fatal("Error reading %s on file %s\n", type, fname);
- }
-
- static void load_show_header()
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- register EXEC *h = &thehdr;
-
- if (sizeof(EXEC) != Fread(inhandle, (long)sizeof(EXEC), h)) {
- read_error("header");
- }
-
- nsyms = h->a_syms / sizeof(NLIST);
- ntrelocs = h->a_trsize / sizeof(RINFO);
- ndrelocs = h->a_drsize / sizeof(RINFO);
-
- toffset = sizeof(EXEC);
- doffset = toffset + h->a_text;
- treloffset = doffset + h->a_data;
- dreloffset = treloffset + h->a_trsize;
- symoffset = dreloffset + h->a_drsize;
- stroffset = symoffset + h->a_syms;
-
- printf("Header for file %s...\n"
- " a_info = %08lX\n"
- " Text size = %08lX\n"
- " Data size = %08lX\n"
- " BSS size = %08lX\n"
- " Sym size, count = %08lX, %5ld\n"
- " Text reloc size, count = %08lX, %5ld\n"
- " Data reloc size, count = %08lX, %5ld\n"
- "\n",
- fname,
- h->a_info,
- h->a_text,
- h->a_data,
- h->a_bss,
- h->a_syms, nsyms,
- h->a_trsize, ntrelocs,
- h->a_drsize, ndrelocs
- );
-
- if (A_OUT_MAGIC != (h->a_info & 0x0000FFFF)) {
- fatal("Bad magic in %s file header", fname);
- }
-
- }
-
- static void load_text()
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- if (thehdr.a_text == 0) {
- return;
- }
- text = emalloc(thehdr.a_text);
- Fseek(toffset, inhandle, SEEK_SET);
- if (thehdr.a_text != Fread(inhandle, thehdr.a_text, text)) {
- read_error("text segment");
- }
- }
-
- static void load_data()
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- if (thehdr.a_data == 0) {
- return;
- }
- data = emalloc(thehdr.a_data);
- Fseek(doffset, inhandle, SEEK_SET);
- if (thehdr.a_data != Fread(inhandle, thehdr.a_data, data)) {
- read_error("data segment");
- }
- }
-
- static void load_symbol_data()
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- long strtabsize;
-
- if (thehdr.a_syms == 0) {
- return;
- }
-
- Fseek(stroffset, inhandle, SEEK_SET);
- if (sizeof(strtabsize) != Fread(inhandle, (long)sizeof(strtabsize), &strtabsize)) {
- read_error("string table size");
- }
-
- symtab = emalloc(thehdr.a_syms);
- strtab = emalloc(strtabsize);
-
- Fseek(symoffset, inhandle, SEEK_SET);
- if (thehdr.a_syms != Fread(inhandle, thehdr.a_syms, symtab)) {
- read_error("symbol table");
- }
- if (strtabsize != Fread(inhandle, strtabsize, strtab)) {
- read_error("string table");
- }
- }
-
- static void show_a_symbol(sym)
- register NLIST *sym;
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- char *symname;
- char *symscope;
- char *symtype;
-
- if (sym->n_strx == 0) {
- symname = "<No Name>";
- } else {
- symname = &strtab[sym->n_strx];
- }
-
- symscope = (sym->n_type & N_EXT) ? "EXT " : " ";
-
- switch (sym->n_type & 0x00FE) {
- case N_ABS: symtype = "ABS "; break;
- case N_TEXT: symtype = "TEXT "; break;
- case N_DATA: symtype = "DATA "; break;
- case N_BSS: symtype = "BSS "; break;
- case N_FN: symtype = "FNAM "; break;
- default: symtype = "UNKN "; break;
- }
-
- printf(" %-24s %s%s %08lX\n", symname, symscope, symtype, sym->n_value);
- }
-
- static void load_show_symbol_table()
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- long i;
-
- load_symbol_data();
-
- printf("Symbol table for file %s\n", fname);
-
- if (thehdr.a_syms == 0) {
- printf("<no symbols in file>\n");
- return;
- }
-
- for (i = 0; i < nsyms; ++i) {
- show_a_symbol(&symtab[i]);
- }
-
- printf("\n");
- }
-
- static void show_a_reloc(rinfo, segaddr)
- register RINFO *rinfo;
- char *segaddr;
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- unsigned char flags;
- unsigned long symnum;
- unsigned long segvalue;
- char *type;
- char *size;
-
- flags = rinfo->r_symboldat & 0x000000FF;
- symnum = rinfo->r_symboldat >> 8;
-
- switch (flags & (RINFO_LONG|RINFO_WORD)) {
- case RINFO_LONG:
- size = "LONG";
- segvalue = *(unsigned long *)(segaddr+rinfo->r_address);
- break;
- case RINFO_WORD:
- size = "WORD";
- segvalue = *(unsigned short *)(segaddr+rinfo->r_address);
- break;
- default:
- size = "BYTE";
- segvalue = *(unsigned char *)(segaddr+rinfo->r_address);
- break;
- }
-
- if (flags & RINFO_PCREL) {
- type = "PC";
- } else {
- type = " ";
- }
-
- printf(" %08lX %s %s =%08lX ", rinfo->r_address, size, type, segvalue);
-
- if (flags & RINFO_EXT) {
- if (symnum > nsyms) {
- printf("?? reference to symbol # %ld of %ld syms in file ??\n",
- symnum, nsyms);
- } else {
- printf("SYM =");
- show_a_symbol(&symtab[symnum]);
- }
- } else {
- switch (symnum & 0x000000FE) {
- case N_TEXT: type = "TEXT"; break;
- case N_DATA: type = "DATA"; break;
- case N_BSS: type = "BSS "; break;
- default: type = "UNKN"; break;
- }
- printf("SEG = %s\n", type, symnum);
- }
- }
-
- static void load_show_reloc(segname, segaddr, offset, count)
- char *segname;
- char *segaddr;
- long offset;
- long count;
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- long i;
- RINFO rinfo;
-
- printf("%s segment relocation info for file %s\n", segname, fname);
- Fseek(offset, inhandle, SEEK_SET);
- for (i = 0; i < count; ++i) {
- if (sizeof(rinfo) != Fread(inhandle, (long)sizeof(rinfo), &rinfo)) {
- read_error("relocation data");
- }
- show_a_reloc(&rinfo, segaddr);
- }
- printf("\n");
- }
-
- static void load_show_file(name)
- char *name;
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- fname = name;
-
- if (0 > (inhandle = Fopen(name, 0))) {
- fatal("Can't open file %s\n", name);
- }
-
- load_show_header();
- load_text();
- load_data();
- load_show_symbol_table();
- load_show_reloc("TEXT", text, treloffset, ntrelocs);
- load_show_reloc("DATA", data, dreloffset, ndrelocs);
- printf("\n");
-
- gfree(symtab);
- gfree(strtab);
- gfree(data);
- gfree(text);
- Fclose(inhandle);
- }
-
- int main(argc, argv)
- int argc;
- char **argv;
- /*****************************************************************************
- *
- ****************************************************************************/
- {
- if (argc < 2) {
- fputs("usage: DUMPAOUT file [file...]\n"
- "\n"
- "Displays header, symbol, and relocation info from\n"
- "one or more GNU a.out object modules.\n"
- ,stderr);
- exit(1);
- }
-
- while (--argc) {
- load_show_file(*++argv);
- }
-
- return 0;
- }
-